/**
 * @author 木人心
 * @version 2.0.0
 */
import { Router } from 'vue-router'
import nProgress from 'nprogress'
import settings from '@/settings'
import Authorization from '@utils/authorization'
import { RouteSecurity } from '@/router/interceptor/config'
import { queryDecrypt, queryEncrypt } from '@/router/interceptor/security'
import { onAuthLaunch } from '@/app'
import { useAppStore } from '@/pinia'
import { ObjectUtil } from '@utils/object-util'
import { setToken } from '@utils/authorization/token'

export default class RouterInterceptor {
  static use (router: Router) {
    // 添加query加密
    queryEncrypt(router)
    // 添加前置守卫
    this.#beforeEach(router)
    // 添加后置守卫
    this.#afterEach(router)
  }

  /**
   * 路由前置守卫
   * @param router
   * @private
   */
  static #beforeEach (router: Router) {
    router.beforeEach(async function (to, from, next) {
      nProgress.start()
      const appStore = useAppStore()

      // 兼容微信小程序进入
      if (to.query.token && /^\/we-applet\/.*/.test(to.path)) setToken(to.query.token as string)

      // 首次包含Token进入
      const firstEntry = ObjectUtil.isEmpty(appStore.userInfo.id) && ObjectUtil.isNotEmpty(Authorization.token)
      if (firstEntry) await Authorization.reloadUser()
      if (firstEntry && appStore.userInfo.id) await onAuthLaunch()
      const result = RouteSecurity.routeCheck(to)
      if (result.isAuthorized) { // 如果授权通过
        next()
      } else if (!result.isAuthenticated) { // 如果没通过是因为没认证
        nProgress.done()
        ElMessage.info('您需要登录才能访问此资源')
        next(RouteSecurity.welcomePath)
      } else { // 没有权限
        ElMessage.warning('您无权访问此资源')
        next(false)
      }
    })
  }

  /**
   * 路由后置守卫
   * @param router
   * @private
   */
  static #afterEach (router: Router) {
    router.afterEach(function (to) {
      queryDecrypt(to)
      // 路由加解密补充了vue3router的params移除的问题，原理是放到query中一起加密，然后在解密分开，然后移除params更新地址栏
      // 但是会导致路由前置守卫进入两次，onBeforeRouteUpdate相关路由也会进入，如果不使用params则不会有影响
      if (Object.keys(to.params).length) {
        const { path, query } = to
        const _to = ObjectUtil.copy({ path, query })
        router.replace(_to)
      }
      nProgress.done()
    })
  }
}
